#ifndef BASELISTESEL_H
#define BASELISTESEL_H

#include "BaseUI.h"
#include "StatusCode.h"
#include <map>

class QVBoxLayout;
class QGroupBox;
class QPushButton;
class QLCDNumber;
class QButtonGroup;

class Key;

/**
 * Classe abstraite, permettant de gérer la sélection dans une liste,
 * avec ou sans coût, donc soit en simple sélection de catégorie ou
 * alors en sélection de compétences, ...
 *
 * Sert aussi de base à BaseMultSel, qui gère la sélection de
 * catégories avec des sous-éléments multiples.
 *
 * Afin de racourcir la liste des QCheckBox, certains boutons peuvent
 * devenir trinaire (càd à trois positions au lieu de On / Off). C'est
 * très utile pour les désavantages par exemple (Phobies modérées /
 * graves, ...). La liste des noms est donc analysée avant de créer
 * l'ensembles des boutons du widget.
 *
 * La classe possède un niveau de sortie propre,
 * BaseSousSel::gestionListe, qui permet de régler le niveau de sortie
 * de tout ce qui est relatif aux opérations sur la liste de noms.
 *
 * @author Johan "Solo" Luisier
 */
class BaseListeSel : public BaseUI
{
  Q_OBJECT
 public:
  BaseListeSel(const unsigned int& nbr, std::string* ptr,
	       const std::string& titre, const std::string& nomFenetre,
	       QWidget* parent = 0);
  BaseListeSel(const unsigned int& nbr, const std::string* ptr,
	       const std::string& titre, const std::string& nomFenetre,
	       QWidget* parent = 0);
  BaseListeSel(const unsigned int& nbr, const std::vector<std::string>* noms,
	       const std::string& titre, const std::string& nomFenetre,
	       QWidget* parent = 0);
  BaseListeSel(const unsigned int& nbr, std::string* ptr,
	       int* ptr_cout, const unsigned int& pp,
	       const std::string& titre, const std::string& nomFenetre,
	       QWidget* parent = 0);
  BaseListeSel(const unsigned int& nbr, const std::string* ptr,
	       int* ptr_cout, const unsigned int& pp,
	       const std::string& titre, const std::string& nomFenetre,
	       QWidget* parent = 0);
  BaseListeSel(const unsigned int& nbr, const std::vector<std::string>* noms,
	       const std::vector<unsigned int>* couts,
	       const unsigned int& pp, const std::string& titre,
	       const std::string& nomFenetre, QWidget* parent = 0);
  BaseListeSel(const BaseListeSel& listeSel);
  virtual ~BaseListeSel();
  virtual StatusCode Choisir(std::vector<unsigned int>& vec);
  static void setLevel(const DebugLevelType& level);
 protected:
  /**
   * Nombre d'items à choix.
   */
  unsigned int dimension;
  /**
   * Nombre de PP pouvant être dépensés.
   */
  int PP;
  /**
   * Variable (dés)activant l'affichage du nombre de PP restants (\e
   * true = affiché, \e false non).
   */
  bool affichePP;
  void prepareAffichage(const std::string& titre);
  void prepareBoutons();
  void analyseListe();
  /**
   * Ensemble qui permet un affichage groupé des QCheckBox.
   */
  QGroupBox *boite;
  /**
   * Ensemble logique des boutons, servant à identifier quel bouton a
   * été sélectionné.
   */
  QButtonGroup *groupe;
  /**
   * Affichage du nombre de PP restant.
   */
  QLCDNumber *nbrPP;
  /**
   * Stocke quel item ont été sélectionnés. Pour chaque item $k$,
   * l'élément $k$ de aChoisi est \e true si cet item est choisi.
   */
  std::vector<bool> aChoisi;
  /**
   * Conteneur des noms des boutons.
   */
  std::vector<std::string> Liste;
  /**
   * Conteneur des coûts, contient des zéros si non applicable.
   */
  std::vector<int> Couts;
 private:
  /**
   * Contient \e true pour l'élément $k$ si l'item $k$ a besoin d'être
   * un tristate (bouton trinaire).
   */
  std::vector<bool> etatsTriples;
  /**
   * Fait correspondre le numéro du bouton à l'item, relation qui peut
   * être non triviale lorsque on a deux noms qui diffère uniquement
   * par (min) / (maj) ou (modérée) / (grave).
   */
  std::map<Key, unsigned int> mapEtatsTriples;
  /**
   * Niveau de sortie de la classe, utilisé pour toutes les méthodes
   * relatives aux manipulations sur la liste des noms.
   */
  static DebugLevelType gestionListe;
 private slots:
  void ajout(const int& i);
  void fermer();
};

#endif // BASELISTESEL_H
